﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;

namespace Sofire.Data.XSql
{
    internal abstract class XSqlTrimNodeBase : XSqlNodeBase, IXSqlTrim
    {
        private string _Trim;
        public string Trim
        {
            get
            {
                return this._Trim;
            }
            set
            {
                this._Trim = value;
            }
        }

        protected override void Load(XmlNode node)
        {
            this._Trim = this.TryGetAttribute(node, XSqlAttributes.Trim);
        }

        private bool Equals(string[] words, string word)
        {
            foreach(var w in words)
            {
                if(string.Equals(word, w, StringComparison.CurrentCultureIgnoreCase)) return true;
            }
            return false;
        }

        private bool FindBeginMatch(string[] trims, string source, out int index, out int length)
        {
            length = 0;
            Queue<char> queue = new Queue<char>(20);

            for(index = 0 ; index < source.Length ; index++)
            {
                var c = source[index];
                if(char.IsWhiteSpace(c))
                {
                    if(queue.Count == 0) continue;
                    length += 1;
                    break;
                }
                queue.Enqueue(c);

                if(!char.IsLetterOrDigit(c))
                {
                    index += queue.Count;
                    break;
                }
            }

            string firstWord = new string(queue.ToArray());
            if(this.Equals(trims, firstWord))
            {
                length += firstWord.Length;
                index -= length;
                if(index < 0) index = 0;
                return true;
            }
            return false;
        }

        private bool FindEndMatch(string[] trims, string source, out int index, out int length)
        {
            length = 0;
            Stack<char> stack = new Stack<char>(20);

            for(index = source.Length - 1 ; index > -1 ; index--)
            {
                var c = source[index];
                if(char.IsWhiteSpace(c))
                {
                    if(stack.Count == 0) continue;
                    index--;
                    break;
                }
                stack.Push(c);
                if(!char.IsLetterOrDigit(c))
                {
                    index -= stack.Count;
                    break;
                }
            }

            string firstWord = new string(stack.ToArray());
            if(this.Equals(trims, firstWord))
            {
                length += firstWord.Length;
                index += length;
                if(index > source.Length - 1) index = source.Length - 1;
                return true;
            }
            return false;
        }

        protected string TrimText(string source)
        {
            if(!string.IsNullOrEmpty(source) && !string.IsNullOrEmpty(this._Trim))
            {
                var trims = this._Trim.Split('|');
                int index, length;
                if(this.FindBeginMatch(trims, source, out index, out length))
                    source = source.Remove(index, length);
                if(this.FindEndMatch(trims, source, out index, out length))
                    source = source.Remove(index, length);

            }
            return source;
        }

    }
}
